<!--
 * Copyright © 2023
 * @Author: zhangxiang
 * @Date: 2023-06-21 10:31:50
 * @LastEditors: zhangxiang
 * @LastEditTime: 2023-09-26 11:31:01
 * @Description:
 *
-->

<template>
  <el-dialog
    class="schedule-strategy-dialog"
    :title="title"
    :visible="show"
    width="700px"
    top="15vh"
    :close-on-click-modal="false"
    :close-on-press-escape="false"
    @close="closeClick"
  >
    <template v-if="!showDetailSetting">
      <el-form
        ref="strategyForm"
        :rules="rules"
        :model="form"
        label-width="auto"
      >
        <el-form-item label="微服务名称" prop="serviceName">
          <el-input
            v-model="form.serviceName"
            :disabled="true"
            placeholder="微服务名称"
          />
        </el-form-item>
        <el-form-item label="服务模型" prop="businessSceneArr">
          <el-cascader
            v-model="form.businessSceneArr"
            style="width: 100%"
            :options="businessSceneOptions"
            placeholder="请选择服务模型"
            :props="{ expandTrigger: 'hover', value: 'value', label: 'value' }"
          />
        </el-form-item>
        <el-form-item
          v-if="isGPUSetting"
          label="服务模型调度"
          prop="serviceModel"
        >
          <el-row type="flex" align="middle">
            <div style="margin-right: 10px">目标数据集</div>
            <el-input-number
              v-model="form.serviceModel.dataSize"
              class="slider"
              :min="1"
              show-input
              :precision="0"
              style="width: 200px"
            />
            <span style="margin: 0 15px 0 10px">张</span>
            <el-tooltip
              effect="dark"
              :content="'模型训练的目标数据集最大数量'"
              placement="top"
            >
              <i
                class="el-icon-info"
                style="font-size: 20px; color: #c3c3c3"
              ></i>
            </el-tooltip>
          </el-row>
          <el-row type="flex" align="middle" style="margin-top: 5px">
            <div style="margin-right: 10px">批处理大小</div>
            <el-select
              v-model="form.serviceModel.batchSize"
              size="medium"
              placeholder="请选择"
              style="width: 200px"
            >
              <el-option
                v-for="item in batchSizeOptions"
                :key="item"
                :label="item"
                :value="item"
              />
            </el-select>
            <el-tooltip
              effect="dark"
              :content="'一次训练的样本数Batchsize'"
              placement="top"
            >
              <i
                class="el-icon-info"
                style="margin-left: 15px; font-size: 20px; color: #c3c3c3"
              ></i>
            </el-tooltip>
          </el-row>
        </el-form-item>
        <!-- 调度策略 -->
        <el-form-item label="调度编排" prop="strategy">
          <div class="strategy">
            <el-row
              type="flex"
              justify="end"
              style="background: #f3f3f3; padding: 0 15px"
            >
              <el-button
                type="text"
                size="medium"
                @click="detailSettingClick"
              >详细配置</el-button>
            </el-row>
            <el-checkbox-group
              v-model="form.strategy"
              size="small"
              class="checkbox"
              @change="strategyCheckgroupChange"
            >
              <el-checkbox
                v-for="item in strategyOptions"
                :key="item.value"
                :label="item.value"
                :disabled="
                  strategyDisabled(item.value) ||
                    (form.strategy.length === 1 &&
                      form.strategy[0] === item.value)
                "
              >{{ item.label }}
              </el-checkbox>
            </el-checkbox-group>
          </div>
        </el-form-item>
        <el-form-item
          v-if="!appCloudScopePublic"
          label="节点区域信息"
          prop="location"
        >
          <el-select
            v-model="form.location"
            size="medium"
            placeholder="请选择"
            style="width: 100%"
          >
            <el-option
              v-for="item in locationOptions"
              :key="item"
              :label="item"
              :value="item"
            />
          </el-select>
        </el-form-item>
        <template v-if="!simple">
          <!-- 简洁模式不展示 -->
          <!-- 调度智能决策相关配置 -->
          <!-- <el-form-item label="调度智能决策" prop="intelligentScheduleActive">
            <el-radio-group
              v-model="form.intelligentScheduleActive"
              class="radios"
            >
              <el-radio :label="0">关闭</el-radio>
              <el-radio :label="1">开启</el-radio>
            </el-radio-group>
          </el-form-item>
          <el-form-item
            v-if="form.intelligentScheduleActive == 1"
            label="智能决策周期"
            prop="intelligentDuration"
          >
            <el-radio-group v-model="form.intelligentDuration" class="radios">
              <el-radio :label="3">3个月</el-radio>
              <el-radio :label="6">6个月</el-radio>
              <el-radio :label="12">1年</el-radio>
            </el-radio-group>
          </el-form-item> -->
        </template>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button size="small" @click="cancelClick">取 消</el-button>
        <el-button
          type="primary"
          size="small"
          :loading="confirmLoading"
          @click="confirmClick"
        >确 定</el-button>
      </div>
    </template>
    <template v-else>
      <el-button
        size="medium"
        type="text"
        icon="el-icon-arrow-left"
        @click="settingBackClick"
      >返回</el-button>
      <ScheduleStrategyDetail
        :options="strategyOptions"
        @confirm="detailConfirmCallback"
      />
    </template>
  </el-dialog>
</template>

<script>
import ScheduleStrategyDetail from '../components/ScheduleStrategyDetail.vue'
import {
  STRATEGY_SCHEDULE_V2,
  STRATEGY_BUSINESS_SCENE,
  GPU_BUSINESS_SCENE
} from '@/utils/cnap/constant'
import { PRIVATE_PROVIDER_AREAS } from '@/utils/constant'
import { addScheduleStrategy } from '@/api/cnap/app-service'

export default {
  name: 'ScheduleStrategyDialog',
  components: {
    ScheduleStrategyDetail
  },
  props: {
    // 展示
    show: {
      type: Boolean,
      default: false
    },
    // 编辑
    isEdit: {
      type: Boolean,
      default: false
    },
    // 简洁模式 只配置调度策略 且数据不存储到后端
    simple: {
      type: Boolean,
      default: false
    },
    // 数据
    info: {
      type: Object,
      default: () => {}
    }
  },
  data() {
    /**
     * @description: 校验服务模型
     * @param {*} rule
     * @param {*} value
     * @param {*} callback
     * @return {*}
     */
    var validateServiceModel = (rule, value, callback) => {
      if (
        Number.isInteger(this.form.serviceModel.dataSize) &&
        this.form.serviceModel.dataSize > 0
      ) {
        if (this.form.serviceModel.batchSize) {
          callback()
        } else {
          callback(new Error('批处理大小不能为空'))
        }
      } else {
        callback(new Error('目标数据集张数只能为正整数'))
      }
    }
    return {
      title: '添加调度策略', // 标题
      locationOptions: PRIVATE_PROVIDER_AREAS,
      businessSceneOptions: STRATEGY_BUSINESS_SCENE, // 业务场景
      strategyOptions: STRATEGY_SCHEDULE_V2, // 策略
      batchSizeOptions: [8, 16, 32, 64],
      form: {
        // 表单
        serviceName: '', // 服务名
        businessSceneArr: [], // 业务场景
        serviceModel: {
          dataSize: 1000, // 模板数据集
          batchSize: 8 // 批处理大小
        },
        location: '',
        intelligentScheduleActive: 0,
        intelligentDuration: 3,
        strategy: ['load', 'price', 'sla']
      },
      // 表单
      rules: {
        // 调度智能决策
        intelligentScheduleActive: [
          { required: true, message: '请选择调度智能决策', trigger: 'blur' }
        ],
        // 调度策略
        strategy: [
          { required: true, message: '请选择调度策略', trigger: 'blur' }
        ],
        // 业务场景
        businessSceneArr: [
          { required: true, message: '请选择调度策略', trigger: 'blur' }
        ],
        // 服务模型调度
        serviceModel: [
          { required: true, validator: validateServiceModel, trigger: 'blur' }
        ]
      },
      confirmLoading: false,
      showDetailSetting: false
    }
  },
  computed: {
    /**
     * @description: 应用资源池是否公有云
     * @return {*}
     */
    appCloudScopePublic() {
      const deployResourceInfo = this.info.deployResourceInfo
      return deployResourceInfo
        ? deployResourceInfo.cloudScope === 'public'
        : false
    },
    /**
     * @description: 是否是GPU配置
     * @return {*}
     */
    isGPUSetting() {
      return (
        this.form.businessSceneArr.length >= 2 &&
        this.form.businessSceneArr[1] === GPU_BUSINESS_SCENE
      )
    }
  },
  watch: {
    /**
     * @description: 监听是否是编辑模式
     * @return {*}
     */
    isEdit: {
      handler(newVal) {
        if (newVal) {
          // 初始化数据
          this.title = '编辑调度策略'
          this.form.serviceName = this.info.serviceName
          // 调度策略相关配置
          const strategyActive = [] // 已选择的策略
          const strategyFormat = []
          // 格式化调度策略
          STRATEGY_SCHEDULE_V2.forEach((item) => {
            if (this.info.scheduleStrategy[item.value]) {
              // 存在相应策略的配置
              const strategySingle = {
                value: item.value,
                label:
                  this.info.scheduleStrategy[item.value].policy || item.label, // 策略名
                percent:
                  Number(this.info.scheduleStrategy[item.value].percent) || 0, // 百分比
                hasFactors: item.hasFactors,
                isCheckbox: item.isCheckbox,
                disabled: this.strategyDisabled(item.value)
              }
              if (Number(this.info.scheduleStrategy[item.value].percent) > 0) {
                strategyActive.push(item.value)
              }
              if (this.info.scheduleStrategy[item.value].param) {
                if (item.value === 'load') {
                  // 负载感知调度策略
                  strategySingle['factors'] = this.info.scheduleStrategy[
                    item.value
                  ].param.loadFactor
                    ? this.info.scheduleStrategy[
                      item.value
                    ].param.loadFactor.split(',')
                    : [] // 配置因子
                } else if (item.value === 'sla') {
                  // sla感知调度策略
                  strategySingle['factors'] = this.info.scheduleStrategy[
                    item.value
                  ].param.slaConfig
                    ? this.info.scheduleStrategy[
                      item.value
                    ].param.slaConfig.split(',')
                    : [] // 配置因子
                } else if (item.value === 'price') {
                  // 成本感知调度策略
                  strategySingle['factor'] =
                    this.info.scheduleStrategy[item.value].param.costType ||
                    'common' // 配置因子
                }
              }
              strategyFormat.push(strategySingle)
            }
          })
          this.strategyOptions = strategyFormat
          this.form.strategy = strategyActive
          // 智能决策相关配置
          this.form.intelligentScheduleActive = Number(
            this.info.intelligentScheduleActive
          ) // 智能决策
          this.form.intelligentDuration = Number(this.info.intelligentDuration)
          if (this.info.businessScene && this.info.businessScene.svcCategory) {
            // 应用场景
            this.form.businessSceneArr = [
              this.info.businessScene.svcCategory,
              this.info.businessScene.svcType
            ]
          }
          if (this.info.serviceModel && this.info.serviceModel.dataSize) {
            this.form.serviceModel = this.info.serviceModel
          }
        } else {
          this.form.serviceName = this.info.serviceNames.join(',')
          this.form.strategy = this.appCloudScopePublic
            ? ['load', 'price', 'sla']
            : ['load', 'sla', 'energy']
          this.strategyOptions = JSON.parse(
            JSON.stringify(STRATEGY_SCHEDULE_V2)
          ).map((item) => {
            item.disabled = this.strategyDisabled(item.value)
            item.percent = item.disabled ? 0 : item.percent
            return item
          })
        }
      },
      immediate: true
    }
  },
  methods: {
    /**
     * @description: 策略是否不可用
     * @return {*}
     */
    strategyDisabled(strategyKey) {
      if (strategyKey === 'price' && !this.appCloudScopePublic) {
        return true
      }
      if (strategyKey === 'energy' && this.appCloudScopePublic) {
        return true
      }
      return false
    },
    /**
     * @description: 详细配置确定
     * @param {*} val
     * @return {*}
     */
    detailConfirmCallback(val) {
      this.strategyOptions = val
      const strategy = []
      this.strategyOptions.forEach((item) => {
        if (Number(item.percent) > 0) {
          strategy.push(item.value)
        }
      })
      this.form.strategy = strategy
      this.showDetailSetting = false
    },
    /**
     * @description: 返回
     * @return {*}
     */
    settingBackClick() {
      this.showDetailSetting = false
    },
    /**
     * @description:
     * @return {*}
     */
    detailSettingClick() {
      this.showDetailSetting = true
    },
    /**
     * @description: 策略选择变化
     * @param {*} val
     * @return {*}
     */
    strategyCheckgroupChange(val) {
      this.strategyOptions.forEach((item, index) => {
        // 修改百分比
        if (this.form.strategy.includes(item.value)) {
          item.percent =
            val.length === 4
              ? 25
              : val.length === 2
                ? 50
                : val.length === 1
                  ? 100
                  : index === 0
                    ? 34
                    : 33
        } else {
          item.percent = 0
        }
      })
    },
    /**
     * @description: 确定
     * @return {*}
     */
    confirmClick() {
      // 校验表单
      this.$refs.strategyForm.validate((valid, obj) => {
        if (valid) {
          // 合法
          this.confirmLoading = true
          // 组装params
          const scheduleParams = []
          const serviceIds = this.isEdit
            ? [this.info.serviceId]
            : this.info.serviceIds
          serviceIds.forEach((serviceId) => {
            const scheduleParam = {
              svcId: serviceId,
              intelligentScheduleActive: this.form.intelligentScheduleActive, // 调度智能决策
              intelligentDuration:
                this.form.intelligentScheduleActive === 1
                  ? this.form.intelligentDuration
                  : 0,
              location: this.form.location,
              businessScene: {
                svcCategory:
                  this.form.businessSceneArr.length >= 2
                    ? this.form.businessSceneArr[0]
                    : '', // 一级
                svcType:
                  this.form.businessSceneArr.length >= 2
                    ? this.form.businessSceneArr[1]
                    : '' // 二级
              },
              serviceModel: this.isGPUSetting ? this.form.serviceModel : null // 服务调度
            }
            this.strategyOptions.forEach((item) => {
              scheduleParam[item.value] = {
                policy: item.label, // 策略名
                percent: item.percent // 百分比
              }
              if (item.hasFactors) {
                if (item.value === 'load') {
                  // 负载 调度因子
                  scheduleParam[item.value]['param'] = {
                    loadFactor: item.factors.join(',')
                  }
                } else if (item.value === 'sla') {
                  // sla 调度因子
                  scheduleParam[item.value]['param'] = {
                    slaConfig: item.factors.join(',')
                  }
                } else if (item.value === 'price') {
                  // price 调度因子
                  scheduleParam[item.value]['param'] = {
                    costType: item.factor
                  }
                }
              }
            })
            scheduleParams.push(scheduleParam)
          })
          if (this.simple) {
            // 简洁模式
            this.$emit('update:show', false)
            this.$emit('simple-callback', scheduleParams) // 抛出数据
            return
          }
          // 添加策略
          addScheduleStrategy(scheduleParams)
            .then((res) => {
              this.$emit('update:show', false)
              if (this.isEdit) {
                this.$emit('edit-success', res.data) // 抛出事件
              } else {
                this.$emit('add-success', res.data) // 抛出事件
              }
            })
            .finally(() => {
              this.confirmLoading = false
            })
        }
      })
    },
    /**
     * @description: 关闭
     * @return {*}
     */
    closeClick() {
      this.$emit('update:show', false)
    },
    /**
     * @description: 取消
     * @return {*}
     */
    cancelClick() {
      this.closeClick()
      this.$emit('cancel')
    }
  }
}
</script>

<style lang="less" scoped>
@import "@/assets/css/common.less";
.schedule-strategy-dialog {
  .strategy {
    background: #fdfdfd;
    border: 1px solid #ececec;

    .checkbox {
      padding: 10px 15px 5px;
      /deep/ .el-checkbox {
        line-height: 36px;
      }
    }
  }
}
</style>
